package com.iisigroup.project.statistics.model;

import java.io.File;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.iisigroup.project.statistics.DependencyEmitter;

public class Function implements Serializable {
    private static final Logger LOGGER = LoggerFactory.getLogger(Function.class);
    /**
     * 
     */
    private static final long serialVersionUID = 1645944907592572451L;

    private String functionName;
    
    private String functionChtName;
    
    private String[] serviceNames;
    
    private Class<?>[] serviceInterfaces;
    
    private String[] serviceImportedClassNames;
    
    private String[] obnfComponentImportedClassNames;
    
    private String obnfImplementedClass;

    private String[] controllerNames;
    
    private Set<String> reallyUsedControllerNames;
    
    private String[] controllerImportedClassNames;
    
    private String[] dtos;
    
    private String[] ftls;
    
    private String[] hibernateEntities;
    
    private String[] xldfDomainObjects;
    
    private Set<String> rscdSet;
    
    private final String expHibernateEntity="tw.gov.moi.domain..*Type";
    
    private final  String expXldfDomainObject="tw.gov.moi.rl.component.xldf.dto..*";
    
    private List<File> jspFileList;
    
    protected    String getAbstractDisplayfunc(final String[] srcArray ){
	String result =StringUtils.EMPTY;
	if(ArrayUtils.isNotEmpty(srcArray)){
   	    List<String> tmpList =new ArrayList<String>();
   	    for (String className : srcArray) {
   		final String[] tmpArray = StringUtils.split(className,".");
   		//2014.12.24決議要加上.java
   		tmpList.add(tmpArray[tmpArray.length-1]+".java");
   	    }
   	    Collections.sort(tmpList);
   	     
   	    result =  StringUtils.join(tmpList,"\r\n");
   	}
	return result;
    }
   
    
    public String[] getAbstractDataName( String[] src,final String srcExpr){
	final Set<String> entitySet = new HashSet<String>();
	if (ArrayUtils.isNotEmpty(controllerImportedClassNames)) {	    
	    for (int i = 0; i < controllerImportedClassNames.length; ++i) {
		String controllerImportedClassName = controllerImportedClassNames[i];
		if (controllerImportedClassName.matches(srcExpr)) {
		    entitySet.add(controllerImportedClassName);
		} 
	    }
	}
	if (ArrayUtils.isNotEmpty(serviceImportedClassNames)) {		
	    for (int i = 0; i < serviceImportedClassNames.length; ++i) {
		String serviceImportedClassName = serviceImportedClassNames[i];
		if (serviceImportedClassName.matches(srcExpr)) {
		    entitySet.add(serviceImportedClassName);
		}
	    }
	}
	if(CollectionUtils.isNotEmpty(entitySet)){
	    final List<String> preList =new ArrayList<String>(entitySet); 
	    Collections.sort(preList);
	    src= preList.toArray(new String []{});
	    
	}else if(src ==null){
	    src =ArrayUtils.EMPTY_STRING_ARRAY;
	}
	return src;
    }
    public String[] getHibernateEntities() {
	hibernateEntities = getAbstractDataName(hibernateEntities, this.expHibernateEntity);
	return hibernateEntities;
    }

    public String[] getXldfDomainObjects() {
	this.xldfDomainObjects = getAbstractDataName(this.xldfDomainObjects, this.expXldfDomainObject);
        return xldfDomainObjects;
    }
    public void setXldfDomainObjects(String[] xldfDomainObjects) {
        this.xldfDomainObjects = xldfDomainObjects;
    }
    public void setHibernateEntities(String[] hibernateEntities) {
        this.hibernateEntities = hibernateEntities;
    }

    public String[] getDtos() {
	if (dtos == null) {
	    final List<String> excludeList = new ArrayList<String>();
	    
	    excludeList.addAll( Arrays.asList( getHibernateEntities() )  );
	    excludeList.addAll( Arrays.asList( getXldfDomainObjects() )  );

	    final Set<String> dtoSet = new HashSet<String>();
	    if (ArrayUtils.isNotEmpty(controllerImportedClassNames)) {
		for (int i = 0; i < controllerImportedClassNames.length; ++i) {
		    String controllerImportedClassName = controllerImportedClassNames[i];
		    if (StringUtils.containsIgnoreCase(controllerImportedClassName, "dto") 
			    && !excludeList.contains(controllerImportedClassName)) {
			dtoSet.add(controllerImportedClassName);
		    } 
		}
	    }
	    if (ArrayUtils.isNotEmpty(serviceImportedClassNames)) {		
		for (int i = 0; i < serviceImportedClassNames.length; ++i) {
		    String serviceImportedClassName = serviceImportedClassNames[i];
		    if (StringUtils.containsIgnoreCase(serviceImportedClassName, "dto")			    
			    && !excludeList.contains(serviceImportedClassName) ) {
			dtoSet.add(serviceImportedClassName);
		    }
		}
	    }
	    dtos = dtoSet.toArray(new String[] {});
	}
        return dtos;
    }

    public void setDtos(String[] dtos) {
	 this.dtos = dtos;
    }
    
    
    public String getDisplayHibernateEntities() {
	final String[] data01 = getHibernateEntities();
	final String[] data02 = getXldfDomainObjects();
	final Set<String> data = new HashSet<String>();
	data.addAll(Arrays.asList(data01));
	for(String className : data02){
	    final  Set<String> importedClasses = DependencyEmitter.extractImportedClasses( className);
	    for(String importedClass : importedClasses){
	        if( importedClass.matches(this.expHibernateEntity)){
	            data.add(importedClass);
	        }
	    }
	}
	
	final String result = getAbstractDisplayfunc(data.toArray(new String[]{}));
	
	return result;
    }
    public String getDisplayTableName() {
    	if("RL02E00".equals(this.functionName)){
            System.out.println("RL02E00");
        }
    	final String[] data01 = getHibernateEntities();
        final String[] data02 = getXldfDomainObjects();
        final Set<String> data = new HashSet<String>();
        data.addAll(Arrays.asList(data01));
        for(String className : data02){
            final  Set<String> importedClasses = DependencyEmitter.extractImportedClasses( className);
            for(String importedClass : importedClasses){
                if( importedClass.matches(this.expHibernateEntity)){
                    data.add(importedClass);
                }
            }
        } 
	
	String result = StringUtils.remove(getAbstractDisplayfunc(data.toArray(new String[]{})),"Type");
	//2014.12.24決議要加上.java導致表格名稱會多了.java
	return result.replace(".java", "");
	
    }
    public String getDisplayRSCDs() {
	final List<String> data = new ArrayList<String>(getRscdSet() );
	Collections.sort(data);
	String result = StringUtils.join(data, "\r\n");
	
	return result;
    }
    public String getDisplayFtlsName() {
	String result = StringUtils.EMPTY;
	if(ArrayUtils.isNotEmpty(ftls)){
	    final List<String> ftlList = new ArrayList<String>(ftls.length);
	    for(String name : ftls){
		ftlList.add(name+".ftl");
	    }
	    result =  StringUtils.join(ftlList,"\r\n");
	}else{
	    
	}
	
	return result;
    }
    public String getDisplayServiceName() {
	final String[] data = getServiceNames();
	

	return  getAbstractDisplayfunc(data);
    }
    
    public String getDisplayDtoName(){
	final String[] data = getDtos();
	return getAbstractDisplayfunc(data);
    }
    
    
    public String getDisplayControllerName(){
	String result = StringUtils.EMPTY;
	final String[] data = getControllerNames();
	String mainData=  getAbstractDisplayfunc(data);
	if (CollectionUtils.isNotEmpty(reallyUsedControllerNames)) {
	    List<String> addition =new ArrayList<String>();
	    for(String name: reallyUsedControllerNames){
		if(!StringUtils.equalsIgnoreCase(name, mainData)){
		    addition.add(name);
		}
	    }
	    if(CollectionUtils.isNotEmpty(addition)){
		result =  new StringBuffer(mainData).append("\r\n(").append( StringUtils.join(addition,",")).append(")").toString();
	    }else{
		result = mainData;
	    }
	  
	   ;
	}
	return  result;
    }
    public String getDisplayControllerUsedCompoenent(){
	final String[] data = getControllerImportedClassNames();

	return  getAbstractDisplayServiceUsedCompoenent(data);
    }
    public String getDisplayServiceInterfaces(){
	String result =StringUtils.EMPTY;
	if(ArrayUtils.isNotEmpty(serviceInterfaces)){
	    List<String> tmpList = new ArrayList<String>();
	    for(Class<?> clazz : serviceInterfaces){
		final 	String simpleClassName = clazz.getSimpleName();
		tmpList.add(simpleClassName);
	    }
	    return  getAbstractDisplayServiceUsedCompoenent(tmpList.toArray(new String[]{}));
	    
	}
	return result;
    }
    public String getDisplayServiceUsedCompoenent(){
        if("RL02E00".equals(this.functionName)){
            System.out.println("RL02E00");
        }
        //TODO 這邊疑似將應該顯示的不小心刪除了
	final String[] data = getServiceImportedClassNames();
	if(ArrayUtils.isNotEmpty(serviceInterfaces)){
	    String[] tmp = null;
	    for(Class<?> clazz : serviceInterfaces){
		final 	String simpleClassName = clazz.getSimpleName();
		 tmp = (String[]) ArrayUtils.removeElement(data, simpleClassName);
	    }
	    return  getAbstractDisplayServiceUsedCompoenent(tmp);
	}else{
	    return  getAbstractDisplayServiceUsedCompoenent(data);
	}
	
    }
    public String getDisplayJsps() {
	String result = StringUtils.EMPTY;
	
	if(CollectionUtils.isNotEmpty(jspFileList)){
	    final List<String> jspFileNameList = new ArrayList<String>();
	    for(File jsp :jspFileList){ 
		final String fileName = jsp.getName();
		jspFileNameList.add(fileName);
	    }
	    Collections.sort(jspFileNameList);
	    result =  StringUtils.join(jspFileNameList, "\r\n");
	}
	return result;
    }
    public String getDisplayObnfUsedCompoenent(){
   	final String[] data = getObnfComponentImportedClassNames();
   	return  getAbstractDisplayServiceUsedCompoenent(data);
   	
       }
   protected String getAbstractDisplayServiceUsedCompoenent(final String[] data ){
       	final String[] dataDtos = getDtos();
	final String[] entities = getHibernateEntities();
	final String[] xldfDomainObjects = getXldfDomainObjects();
	
	final Set<String> excludeSet = new HashSet<String>();
	
	excludeSet.addAll(Arrays.asList(dataDtos));
	excludeSet.addAll(Arrays.asList(entities));
	excludeSet.addAll(Arrays.asList(xldfDomainObjects));
	
	List<String> menu =new ArrayList<String>();
	if (ArrayUtils.isNotEmpty(data)) {
	    for (final String className : data) {
		if (!excludeSet.contains(className)) {
		    menu.add(className);
		}
	    }
	}
	final String[] finalData =  menu.toArray(new String[]{});
	
	return  getAbstractDisplayfunc(finalData);
   }

    public String getFunctionName() {
        return functionName;
    }

    public void setFunctionName(String functionName) {
        this.functionName = functionName;
    }


    public String[] getControllerImportedClassNames() {
        return controllerImportedClassNames;
    }

    public void setControllerImportedClassNames(String[] controllerImportedClassNames) {
        this.controllerImportedClassNames = controllerImportedClassNames;
    }

    public String getFunctionChtName() {
        return functionChtName;
    }

    public void setFunctionChtName(String functionChtName) {
        this.functionChtName = functionChtName;
    }

    public String[] getServiceImportedClassNames() {
        return serviceImportedClassNames;
    }

    public void setServiceImportedClassNames(String[] serviceImportedClassNames) {
        this.serviceImportedClassNames = serviceImportedClassNames;
    }

    public String[] getControllerNames() {
        return controllerNames;
    }

    public void setControllerNames(String[] controllerNames) {
        this.controllerNames = controllerNames;
    }

    public String[] getServiceNames() {
        return serviceNames;
    }

    public void setServiceNames(String[] serviceNames) {
        this.serviceNames = serviceNames;
    }


    public String[] getFtls() {
        return ftls;
    }

    public void setFtls(String[] ftls) {
        this.ftls = ftls;
    }


    public Class<?>[] getServiceInterfaces() {
        return serviceInterfaces;
    }


    public void setServiceInterfaces(Class<?>[] serviceInterfaces) {
        this.serviceInterfaces = serviceInterfaces;
    }


    public String[] getObnfComponentImportedClassNames() {
        return obnfComponentImportedClassNames;
    }


    public void setObnfComponentImportedClassNames(String[] obnfComponentImportedClassNames) {
        this.obnfComponentImportedClassNames = obnfComponentImportedClassNames;
    }


    public String getObnfImplementedClass() {
        return obnfImplementedClass;
    }


    public void setObnfImplementedClass(String obnfImplementedClass) {
        this.obnfImplementedClass = obnfImplementedClass;
    }


    public Set<String> getRscdSet() {
	if(rscdSet == null){
	    rscdSet =new HashSet<String>();
	}
        return rscdSet;
    }


    public void setRscdSet(Set<String> rscdSet) {
        this.rscdSet = rscdSet;
    }


    public List<File> getJspFileList() {
	if(jspFileList == null ){
	    jspFileList = new ArrayList<File>();
	}
        return jspFileList;
    }


    public void setJspFileList(List<File> jspFileList) {
        this.jspFileList = jspFileList;
    }


    public Set<String> getReallyUsedControllerNames() {
        return reallyUsedControllerNames;
    }


    public void setReallyUsedControllerNames(Set<String> reallyUsedControllerNames) {
        this.reallyUsedControllerNames = reallyUsedControllerNames;
    }
    
}
